
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Game2DAnimationAPI
{
    public class Matrix
    {
	    float[,] _matrix = new float[3,3];
	    void Mul(float[,] m) {
		    float[,] tmp = new float[2,3];

		    tmp[0,0] = _matrix[0,0];
		    tmp[0,1] = _matrix[0,1];
		    tmp[0,2] = _matrix[0,2];
		    tmp[1,0] = _matrix[1,0];
		    tmp[1,1] = _matrix[1,1];
		    tmp[1,2] = _matrix[1,2];            
            
            _matrix[0,0] = m[0,0] * tmp[0,0] + m[0,1] * tmp[1,0] + m[0,2] * _matrix[2,0];
            _matrix[0,1] = m[0,0] * tmp[0,1] + m[0,1] * tmp[1,1] + m[0,2] * _matrix[2,1];
            _matrix[0,2] = m[0,0] * tmp[0,2] + m[0,1] * tmp[1,2] + m[0,2] * _matrix[2,2];

            _matrix[1,0] = m[1,0] * tmp[0,0] + m[1,1] * tmp[1,0] + m[1,2] * _matrix[2,0];
            _matrix[1,1] = m[1,0] * tmp[0,1] + m[1,1] * tmp[1,1] + m[1,2] * _matrix[2,1];
            _matrix[1,2] = m[1,0] * tmp[0,2] + m[1,1] * tmp[1,2] + m[1,2] * _matrix[2,2];
        
            _matrix[2,0] = m[2,0] * tmp[0,0] + m[2,1] * tmp[1,0] + m[2,2] * _matrix[2,0];
            _matrix[2,1] = m[2,0] * tmp[0,1] + m[2,1] * tmp[1,1] + m[2,2] * _matrix[2,1];
            _matrix[2,2] = m[2,0] * tmp[0,2] + m[2,1] * tmp[1,2] + m[2,2] * _matrix[2,2];
	    }
 
	    float Index(int i, int j) { return _matrix[i,j]; }
	    public void Unit() {
		    _matrix[0,0] = 1; _matrix[0,1] = 0; _matrix[0,2] = 0;
		    _matrix[1,0] = 0; _matrix[1,1] = 1; _matrix[1,2] = 0;
		    _matrix[2,0] = 0; _matrix[2,1] = 0; _matrix[2,2] = 1;
	    }
        public Matrix()
        {
            Unit();
        }
        public Matrix(Matrix m)
        {
            Unit();
            Mul(m);
        }
        public void Rotate(float angle)
        {
            float ca = (float)(Math.Cos(angle));
            float sa = (float)(Math.Sin(angle));

            float m0 = (ca * _matrix[0,0] + sa * _matrix[1,0]);
            float m1 = (ca * _matrix[0,1] + sa * _matrix[1,1]);
            float m2 = (ca * _matrix[0,2] + sa * _matrix[1,2]);
        
            _matrix[1,0] = ca * _matrix[1,0] - sa * _matrix[0,0];
            _matrix[1,1] = ca * _matrix[1,1] - sa * _matrix[0,1];
            _matrix[1,2] = ca * _matrix[1,2] - sa * _matrix[0,2];
        
            _matrix[0,0] = m0;
            _matrix[0,1] = m1;
            _matrix[0,2] = m2;
        }
        public void Scale(float scx, float scy)
        {
            _matrix[0,0] *= scx;
            _matrix[0,1] *= scx;
            _matrix[0,2] *= scx;
        
            _matrix[1,0] *= scy;
            _matrix[1,1] *= scy;
            _matrix[1,2] *= scy;
        }
        public void Move(float x, float y)
        {
            _matrix[2,0] += (x * _matrix[0,0] + y * _matrix[1,0]);
            _matrix[2,1] += (x * _matrix[0,1] + y * _matrix[1,1]);
            _matrix[2,2] += (x * _matrix[0,2] + y * _matrix[1,2]);
	
        }
        public void Mul(Matrix transform)
        {
		    Mul(transform._matrix);
	    }
        public void Mul(float[] x, float[] y)
        {
		    float tx = x[0];
		    x[0] = _matrix[0,0] * tx + _matrix[1,0] * y[0] + _matrix[2,0];
		    y[0] = _matrix[0,1] * tx + _matrix[1,1] * y[0] + _matrix[2,1];
	    }
        public void Mul(float sx, float sy, float[] x, float[] y)
        {
		    x[0] = _matrix[0,0] * sx + _matrix[1,0] * sy + _matrix[2,0];
		    y[0] = _matrix[0,1] * sx + _matrix[1,1] * sy + _matrix[2,1];
	    }
        public float Determinant()
        {
		    return _matrix[0,0]*_matrix[1,1]*_matrix[2,2] 
					    - _matrix[0,0]*_matrix[1,2]*_matrix[2,1] 
					    - _matrix[0,1]*_matrix[1,0]*_matrix[2,2] 
					    + _matrix[0,1]*_matrix[1,2]*_matrix[2,0] 
					    + _matrix[0,2]*_matrix[1,0]*_matrix[2,1] 
					    - _matrix[0,2]*_matrix[1,1]*_matrix[2,0];
	    }
        public void Flip()
        {
		    float t;
		
		    t = _matrix[1,0];
		    _matrix[1,0] = _matrix[0,1];
		    _matrix[0,1] = t;

		    t = _matrix[1,2];
		    _matrix[1,2] = _matrix[2,1];
		    _matrix[2,1] = t;

		    t = _matrix[2,0];
		    _matrix[2,0] = _matrix[0,2];
		    _matrix[0,2] = t;
	    }
        public void Mul(float f)
        {
		    _matrix[0,0] *= f;
		    _matrix[1,0] *= f;
		    _matrix[2,0] *= f;

		    _matrix[0,1] *= f;
		    _matrix[1,1] *= f;
		    _matrix[2,1] *= f;

		    _matrix[0,2] *= f;
		    _matrix[1,2] *= f;
		    _matrix[2,2] *= f;
	    }
        public void MakeRevers(Matrix transform)
        {
		    float det = transform.Determinant();

		    _matrix[0,0] = (transform._matrix[1,1] * transform._matrix[2,2] - transform._matrix[2,1] * transform._matrix[1,2]);
		    _matrix[1,0] = -(transform._matrix[0,1] * transform._matrix[2,2] - transform._matrix[2,1] * transform._matrix[0,2]);
		    _matrix[2,0] = (transform._matrix[0,1] * transform._matrix[1,2] - transform._matrix[1,1] * transform._matrix[0,2]);

		    _matrix[0,1] = -(transform._matrix[1,0] * transform._matrix[2,2] - transform._matrix[2,0] * transform._matrix[1,2]);
		    _matrix[1,1] = (transform._matrix[0,0] * transform._matrix[2,2] - transform._matrix[2,0] * transform._matrix[0,2]);
		    _matrix[2,1] = -(transform._matrix[0,0] * transform._matrix[1,2] - transform._matrix[1,0] * transform._matrix[0,2]);

		    _matrix[0,2] = (transform._matrix[1,0] * transform._matrix[2,1] - transform._matrix[2,0] * transform._matrix[1,1]);
		    _matrix[1,2] = -(transform._matrix[0,0] * transform._matrix[2,1] - transform._matrix[2,0] * transform._matrix[0,1]);
		    _matrix[2,2] = (transform._matrix[0,0] * transform._matrix[1,1] - transform._matrix[1,0] * transform._matrix[0,1]);

		    Flip();

		    Mul(1 / det);
	    }
        public void GetScale(float[] sx, float[] sy)
        {
		    sx[0] = _matrix[0,0];
		    sy[0] = _matrix[1,1];
	    }
    }
}